﻿using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Telepathy;
using Telepathy.Protocols;
using UnityEngine;
using UtilsTools;

namespace Telepathy.NetworkBase
{
    public enum TcpModel
    {
        None,
        Client,
        Server
    }
    public class BaseTcp : MonoBehaviour
    {
        public string Ip = "127.0.0.1";
        public int Port = 34567;

        ulong MsgIndex = 0;
        protected string MsgStringId
        {
            get
            {
                MsgIndex++;
                if (MsgIndex >= ulong.MaxValue) MsgIndex = 0;
                return SystemInfo.deviceUniqueIdentifier + MsgIndex;
            }
        }

        protected Client client { get; private set; }
        protected Server server { get; private set; }

        TcpModel tcpModel = TcpModel.None;

        protected SetIniConfig iniConfig;


        protected virtual void Awake()
        {
            // update even if window isn't focused, otherwise we don't receive.
            Application.runInBackground = true;
            // use Debug.Log functions for Telepathy so we can see it in the console
            Telepathy.Logger.Log = Debug.Log;
            Telepathy.Logger.LogWarning = Debug.LogWarning;
            Telepathy.Logger.LogError = Debug.LogError;

            string configPath = Application.streamingAssetsPath + "/Config/config.ini";
            iniConfig = new SetIniConfig(configPath);
            OnConfig();
        }

        protected virtual void Update()
        {
            StartRecvUpdate(tcpModel);
        }

        private void OnConfig()
        {
            string section = "NETWORK";

            Ip = iniConfig.ReadString(section, "ip", Ip).Trim();
            iniConfig.WriteString(section, "ip", Ip);

            Port = iniConfig.ReadInt(section, "port", Port);
            iniConfig.WriteInt(section, "port", Port);
        }
        /// <summary>
        /// 开始客户端服务
        /// </summary>
        /// <returns></returns>
        protected bool StartClient(string ip, int port)
        {
            try
            {
                client = new Client();
                client.Connect(ip, port);
                tcpModel = TcpModel.Client;
                return true;
            }
            catch (Exception ex)
            {
                Debug.LogError("客户端Tcp启动失败! \r\n" + ex);
            }
            return true;
        }

        /// <summary>
        /// 开始服务端
        /// </summary>
        /// <returns></returns>
        protected bool StartServer(int port)
        {
            try
            {
                server = new Server();
                server.Start(port);
                tcpModel = TcpModel.Server;
                return true;
            }
            catch (Exception ex)
            {
                Debug.LogError("服务端Tcp启动失败! \r\n" + ex);
            }
            return false;
        }

        void StartRecvUpdate(TcpModel model)
        {
            switch (model)
            {
                case TcpModel.Client:
                    if (client == null) break;
                    Connected(client, client.Connected);
                    break;
                case TcpModel.Server:
                    if (server == null) break;
                    Connected(server, server.Active);
                    break;
            }
        }

        private void Connected(Telepathy.Common common, bool state)
        {
            if (state)
            {
                Telepathy.Message msg;
                while (common.GetNextMessage(out msg))
                {
                    switch (msg.eventType)
                    {
                        case Telepathy.EventType.Connected:
                            OnConnected(msg);
                            break;
                        case Telepathy.EventType.Data:
                            OnRecvHandle(msg);
                            break;
                        case Telepathy.EventType.Disconnected:
                            OnDisconnected(msg);
                            break;
                    }
                }
            }
        }

        void OnRecvHandle(Telepathy.Message msg)
        {
            MessageBase baseMsg = MessageBase.Deserialize(msg.data);
            HeaderType headerType = baseMsg.headerType;
            switch (headerType)
            {
                case HeaderType.Content:
                    Protocols.MyMessage myMsg = new Protocols.MyMessage();
                    myMsg.MsgBase = baseMsg;
                    OnRecvMessage(msg.connectionId,myMsg);
                    break;
                case HeaderType.Login:
                    Protocols.LoginMessage loginMsg = new Protocols.LoginMessage();
                    loginMsg.MsgBase = baseMsg;
                    OnLoginMessage(msg.connectionId, loginMsg);
                    break;
                case HeaderType.Heart:
                    Protocols.HeartMessage heardMsg = new Protocols.HeartMessage();
                    heardMsg.MsgBase = baseMsg;
                    OnHeardMessage(msg.connectionId, heardMsg);
                    break;
            }
            
        }
        protected virtual void OnConnected(Message myMsg) { }
        protected virtual void OnDisconnected(Message msg){}
        protected virtual void OnRecvMessage(int connID, Protocols.MyMessage msg){ }
        protected virtual void OnLoginMessage(int connID, Protocols.LoginMessage msg) { }
        protected virtual void OnHeardMessage(int connID, Protocols.HeartMessage msg) { }

        /// <summary>
        /// 客户端发送消息到服务端
        /// </summary>
        /// <param name="data"></param>
        public virtual bool SendToserver(byte[] data)
        {
            if (client == null && !client.Connected) {
                Debug.LogError("客户端Tcp未启动!");
                return false;
            }
            return client.Send(data);
        }

        /// <summary>
        /// 服务端发送消息到客户端
        /// </summary>
        /// <param name="clientID"></param>
        /// <param name="data"></param>
        public virtual bool SendToClient(int clientID, byte[] data)
        {
            if (server == null && !server.Active)
            {
                Debug.LogError("服务端Tcp未启动!");
                return false;
            }
            return server.Send(clientID, data);
        }

        /// <summary>
        /// 实例化消息类协议
        /// </summary>
        /// <param name="strMsg"></param>
        /// <param name="bytes"></param>
        /// <param name="headerType"></param>
        /// <returns></returns>
        protected MessageBase GetMessageBase(string strMsg, byte[] bytes, HeaderType headerType)
        {
            MessageBase myMsg = new MessageBase(headerType);
            myMsg.text = strMsg;
            if (bytes != null) myMsg.bytes = bytes;
            return myMsg;
        }

        protected virtual void Destroy()
        {
            if (client != null) client.Disconnect();
            if (server != null) server.Stop();
        }

        private void OnDestroy()
        {
            Destroy();
        }

        private void OnApplicationQuit()
        {
            Destroy();
        }
    }
}
